﻿using System;
using System.Diagnostics.CodeAnalysis;

namespace Liphofra.Core
{
    /// <summary>
    /// Describes a simple IoC container for Windows Phone.
    /// </summary>
    public interface IServiceLocator
    {
        /// <summary>
        /// Registers a mapping between interface and corresponding implementation.
        /// </summary>
        /// <typeparam name="TInterface">The type of the interface.</typeparam>
        /// <typeparam name="TImplementation">The type of the implementation.</typeparam>
        [SuppressMessage("Microsoft.Design", 
            "CA1004:GenericMethodsShouldProvideTypeParameter", 
            Justification = "We need to do a generice type to type mapping here and cannot work with instances and/or arguments.")]
        void Register<TInterface, TImplementation>();

        /// <summary>
        /// Registers the specified instance for the given type. This instance will be returned for this type for successive calls of <see cref="Resolve{T}"/> or <see cref="Resolve"/>.
        /// </summary>
        /// <typeparam name="T">The type to register this instance for.</typeparam>
        /// <param name="instance">The instance to register for the given type.</param>
        void Register<T>(T instance);

        /// <summary>
        /// Registers the specified function as mechanism to gain access to an instance of type <typeparamref name="T"/>. This will be used in successive calls of <see cref="Resolve{T}"/> or <see cref="Resolve"/>.
        /// </summary>
        /// <typeparam name="T">The type the function is registered for.</typeparam>
        /// <param name="func">The function to use to retrieve an instance of <typeparamref name="T"/>.</param>
        void Register<T>(Func<T> func);

        /// <summary>
        /// Resolves an instance of the given type <typeparamref name="T"/>.
        /// </summary>
        /// <typeparam name="T">The type that should be resolved.</typeparam>
        /// <returns>An instance of the requested type retrieved using the previously specified registration, or using its constructor. Dependencies are resolved recursively.</returns>
        T Resolve<T>();

        /// <summary>
        /// Resolves an instance of the specified type.
        /// </summary>
        /// <param name="type">The type to resolve an instance for.</param>
        /// <returns>An instance of the requested type retrieved using the previously specified registration, or using its constructor. Dependencies are resolved recursively.</returns>
        object Resolve(Type type);
    }
}